/** @file */
#include "osc-control.hpp"
#include <cstdlib>
#include <cstring>
#include <stdio.h>

/** Identification code of the oscilloscope */
const char REF_ID[] = "Agilent Technologies,DSOX91604A,MY51260105,03.10.0005";

/** IP address of the oscilloscope */
const char serv_ip[] = "127.0.0.1";

/** Port number for TCP/IP communication */
int port = 5025;

osc_control::osc_control ():tcp_client ((char *) serv_ip, port)
{

//Connect to socket
  tcp_connect ();
  /*try{
     if( ! testReady() )
     throw "Warning: device is busy!";
     }
     catch(...)
     {throw;}
   */
}

bool osc_control::identify ()
{
  char
    ID[54];
  try
  {
    getString ("*IDN?\n", ID, 53);
  }
  catch ( ...)
  {
    throw;
  }

  return (!strcmp (REF_ID, ID));
}

bool osc_control::preset ()
{
  try
  {
    int
      ret =
      getInteger
      (":SYSTEM:HEADER OFF;:WAV:SOUR CHAN1;FORM BYTE;BYT MSBF;:WAV:VIEW MAIN;*OPC?\n");

    return (ret == 1);
  }
  catch ( ...)
  {
    throw;
  }
}

int
osc_control::number_of_points ()
{
  try
  {
    int data_count = getInteger (":WAV:POIN?\n");
    return data_count;
  }
  catch ( ...)
  {
    throw;
  }
}

void
osc_control::getTrace8 (int8_t data[], unsigned count)
{
  try
  {
    int actual_count = number_of_points ();

    if (count != actual_count)
      throw "Requested trace length does not match the returned length";

    getBinaryArray (":DIG;:WAV:DATA?\n", (char *) data, count);
  }
  catch ( ...)
  {
    throw;
  }
}

bool osc_control::testReady ()
{
  try
  {
    tcp_send ("*OPC?\n");
  }
  catch ( ...)
  {
    throw;
  }
  char
  c[2] = { 0 };
  tcp_read (c, 2);

  return (c[0] == '1');
}

int
osc_control::getInteger (char command[])
{
  try
  {

    tcp_send (command);

    // Loop until line return
    unsigned long idx = 0;
    do
      {
	tcp_read (buffer + idx, 1);
	if (buffer[idx] == '\n')
	  break;
	idx++;
      }
    while (idx < max_integer_len - 1);

    if (idx >= max_integer_len - 1)
      throw "Warning: received integer too long.";

    buffer[idx] = 0;		// terminate the string
  }
  catch ( ...)
  {
    throw;
  }

  int number = std::atoi (buffer);

  return number;
}

void
osc_control::getString (char command[], char str[], unsigned long count)
{
  try
  {
    tcp_send (command);
    tcp_read (str, count + 1);
  }
  catch ( ...)
  {
    throw;
  }

  // the last byte must be '\n'
  if (str[count] != '\n')
    throw "String longer than expected";

  // Terminate the string no matter what the last byte is
  str[count] = '\0';
}

void
osc_control::getBinaryArray (char command[], char *IntArray,
			     unsigned long count)
{
  try
  {

    tcp_send (command);

// Get '#4'
    char header1[2];
    tcp_read (header1, 2);

    if (header1[0] != '#')
      throw "Response is not a binary array";
//else
    int header2_count = (header1[1] - '0');


// Get #4'1001'
    char header2[10];
    tcp_read (header2, header2_count);
    header2[header2_count + 1] = 0;

    int array_count = std::atoi (header2);
    if (array_count == 0)
      throw "Response is an empty binary array";
    else if (array_count != count)
      throw "Binary length doesn't match integer array length";
    tcp_read (IntArray, array_count);

    char c;
    tcp_read (&c, 1);		//Pop termination character


  }
  catch ( ...)
  {
    throw;
  }
}

osc_control::~osc_control ()
{
  tcp_disconnect ();

}
